« 2/25/2008 – Paging result sets in SQL Server 2005 | Main | 3/13/2008 – New book from Joe Celko »

3/9/2008 – Accessing the INSERTED/DELETED tables outside a trigger

If you've ever written a database trigger in SQL Server, you know that the INSERTED/DELETED system tables are great for seeing the contents of rows before and after an update.

Unfortunately, as recently as SQL Server 2000, it wasn't easy getting information from INSERTED/DELETED rows outside of a trigger. As a matter of fact, INSERTED/DELETED tables were only visible inside a trigger. The best you could do was write code inside a trigger, to copy data from INSERTED/DELETED into temp tables, and then read the temp tables outside the trigger. Sure, you could make it work, but it was like eating broccoli – yuck.

(My apologies to all you broccoli-lovers out there)

Well, SQL Server 2005 introduced a new capability called OUTPUT, which you could append to an INSERT/UPDATE/DELETE statement. Essentially, OUTPUT allows you to specify the rows in the INSERTED/DELETED system tables – so you can actually issue an UPDATE statement, and also get values from the INSERTED/DELETED tables as a result set. Sound too good to be true? Well, check out this little sample:

-- Create a test table variable, add three rows to it, and then update the first two
DECLARE
@tTest TABLE ( IDCol int identity,Amount decimal(10,2))
INSERT INTO @tTest VALUES (100)
INSERT INTO @tTest VALUES (200)
INSERT INTO @tTest VALUES (300)

UPDATE TOP(2) @tTest SET Amount = Amount * 10
    OUTPUT INSERTED.IDCol, DELETED.Amount as OldAmount, Inserted.Amount as NewAmount

-- will yield the following:
IDCol     OldAmount         NewAmount
1         100.00            1000.00
2         200.00            2000.00

All I've done in the sample above is add an OUTPUT statement to the end of the UPDATE statement, and then I specified the columns. Obviously this is a simple example – but if the table contained calculated columns, or columns affected by a trigger, the OUTPUT of any columns from the INSERTED table would reflect those calculations.

Pretty cool, eh? This means no more round trips back to the server (or at least no more additional SQL statements) to retrieve what changed.

Now, there's one more thing – suppose you wanted to direct the values from INSERTED/DELETED into a table variable. You could the following, to redirect the OUTPUT to a table variable. (This way, I can use OUTPUT for multiple tables)

DECLARE @tResults TABLE (IDCol int, OldAmount decimal(10,2), NewAmount decimal(10,2))

UPDATE
TOP(2) @tTest
    SET Amount = Amount * 10
        OUTPUT INSERTED.IDCOL, DELETED.AMOUNT, INSERTED.AMOUNT INTO @tResults

SELECT
* FROM @tResults

KG

Comments

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

My Photo